home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir37 / ms_sh23s.zip / SRC / STDARGV.C < prev    next >
C/C++ Source or Header  |  1994-08-26  |  19KB  |  908 lines

  1. /* MS-DOS stdargv Function
  2.  *
  3.  * MS-DOS stdargv - Copyright (c) 1990,4 Data Logic Limited.
  4.  *
  5.  * This code is subject to the following copyright restrictions:
  6.  *
  7.  * 1.  Redistribution and use in source and binary forms are permitted
  8.  *     provided that the above copyright notice is duplicated in the
  9.  *     source form.
  10.  *
  11.  *    $Header: /usr/users/istewart/shell/sh2.3/Release/RCS/stdargv.c,v 2.9 1994/08/25 20:49:11 istewart Exp $
  12.  *
  13.  *    $Log: stdargv.c,v $
  14.  *    Revision 2.9  1994/08/25  20:49:11  istewart
  15.  *    MS Shell 2.3 Release
  16.  *
  17.  *    Revision 2.8  1994/02/01  10:25:20  istewart
  18.  *    Release 2.3 Beta 2, including first NT port
  19.  *
  20.  *    Revision 2.7  1994/01/20  14:51:43  istewart
  21.  *    Release 2.3 Beta 1
  22.  *
  23.  *    Revision 2.6  1994/01/11  17:55:25  istewart
  24.  *    Release 2.3 Beta 0 patches
  25.  *
  26.  *    Revision 2.5  1993/08/25  16:04:22  istewart
  27.  *    Add support for MSC 6 which requires osmajor and osminor to be set up
  28.  *    for MSDOS.
  29.  *
  30.  *    Revision 2.4  1993/06/14  10:59:58  istewart
  31.  *    More changes for 223 beta
  32.  *
  33.  *    Revision 2.3  1993/06/02  09:54:21  istewart
  34.  *    Beta 223 Updates - see Notes file
  35.  *
  36.  *    Revision 2.2  1992/12/14  11:12:37  istewart
  37.  *    BETA 215 Fixes and 2.1 Release
  38.  *
  39.  *    Revision 2.1  1992/11/06  10:03:44  istewart
  40.  *    214 Beta test updates
  41.  *
  42.  *    Revision 2.0  1992/04/13  17:39:09  Ian_Stewartson
  43.  *    MS-Shell 2.0 Baseline release
  44.  *
  45.  *
  46.  *
  47.  * MODULE DEFINITION:
  48.  *
  49.  * This function expandes the command line parameters in a UNIX like manner.
  50.  * Wild character *?[] are allowed in file names. @filename causes command lines
  51.  * to be read from filename.  Strings between " or ' are not expanded.  All
  52.  * entries in the array are malloced.
  53.  *
  54.  * This function replaces the standard Microsoft C5.1 & C6.0 C Run-Time
  55.  * start up line processing function (_setargv in stdargv.obj).
  56.  *
  57.  * For OS/2 2.x, this function replaces the standard IBM C Set/2 C Run-Time
  58.  * start up line processing function (_setuparg in stdargv.obj).
  59.  *
  60.  * For Turbo C, this function replaces the standard Borland C Run-Time
  61.  * start up line processing function (_setargv).
  62.  *
  63.  * For WatCom C, this function replaces the standard WatCom C Run-Time
  64.  * start up line processing function (__Init_Argv).
  65.  *
  66.  * To get the OS2 16-bit version, compile with -DOS2
  67.  * To get the OS2 32-bit version, compile with -D__OS2__
  68.  * To get the NT 32-bit version, compile with -DWIN32
  69.  *
  70.  * Author:
  71.  *    Ian Stewartson
  72.  *    Data Logic, Queens House, Greenhill Way
  73.  *    Harrow, Middlesex  HA1 1YR, UK.
  74.  *    istewart@datlog.co.uk or ukc!datlog!istewart
  75.  */
  76.  
  77. #include <sys/types.h>            /* MS-DOS type definitions      */
  78. #include <sys/stat.h>            /* File status definitions    */
  79. #include <stdio.h>            /* Standard I/O delarations     */
  80. #include <stdlib.h>            /* Standard library functions   */
  81. #include <errno.h>            /* Error number declarations    */
  82.  
  83. #if defined (OS2) || defined (__OS2__)
  84. #  define INCL_DOSSESMGR
  85. #  define INCL_DOSMEMMGR
  86. #  define INCL_DOSPROCESS
  87. #  define INCL_DOSMODULEMGR
  88. #  define INCL_WINSWITCHLIST
  89. #  include <os2.h>            /* OS2 functions declarations   */
  90. #elif (WIN32)
  91. #  include <windows.h>            /* WIN NT functions declarations   */
  92. #else
  93. #  include <dos.h>            /* DOS functions declarations   */
  94. #  include <bios.h>            /* BIOS functions declarations  */
  95. #endif
  96.  
  97. #include <ctype.h>            /* Character type declarations  */
  98. #include <string.h>            /* String library functions     */
  99. #include <limits.h>            /* String library functions     */
  100. #include <fcntl.h>            /* File Control Declarations    */
  101. #include <dirent.h>            /* Direction I/O functions    */
  102. #include <unistd.h>
  103. #include <glob.h>            /* Globbing functions        */
  104.  
  105. /*
  106.  *  DATA DEFINITIONS:
  107.  */
  108.  
  109. #define MAX_LINE    160        /* Max line length        */
  110. #define S_ENTRY        sizeof (char *)
  111.  
  112. /*
  113.  *  DATA DECLARATIONS:
  114.  */
  115.  
  116. static void    _Ex_CommandLine (char *);    /* Expand file        */
  117. static void    _Ex_ExpandIndirectFile (char *);
  118. static char    *_Ex_GetSpace (int, char *);    /* Get space        */
  119. static void    _Ex_AddArgument (char *);    /* Add argument        */
  120. static char    *_Ex_SkipWhiteSpace (char *);    /* Skip spaces        */
  121. static char    *_Ex_ConvertToUnixFormat (char *);
  122. static void    _Ex_ExpandField (char *);    /* Split file name    */
  123. static void    _Ex_FatalError (int, char *, char *);
  124. static char    *_Ex_ConvertEnvVariables (char *);
  125. static char    *_EX_OutOfMemory = "%s: %s\n";
  126.  
  127. #if defined (OS2) || defined (__OS2__)
  128. static void    _Ex_ProcessEMXArguments (char *);
  129. static void    _Ex_SetUpWindowName (void);
  130. #elif (WIN32)
  131. static void    _Ex_SetUpWindowName (void);
  132. #endif
  133.  
  134. /*
  135.  * Command Line pointers
  136.  */
  137.  
  138. #if defined (__OS2__)
  139. #  define ARG_ARRAY    _argv
  140. #  define ARG_COUNT    _argc
  141. #  define ENTRY_POINT    _setuparg
  142. #elif defined (__TURBOC__)
  143. #  define ARG_ARRAY    _C0argv
  144. #  define ARG_COUNT    _C0argc
  145. #  define ENTRY_POINT    _setargv
  146. #elif defined (__WATCOMC__)
  147. #  define ARG_ARRAY    ___Argv
  148. #  define ARG_COUNT    ___Argc
  149. #  define ENTRY_POINT    __Init_Argv
  150. #else
  151. #  define ARG_ARRAY    __argv
  152. #  define ARG_COUNT    __argc
  153. #  define ENTRY_POINT    _setargv
  154. #endif
  155.  
  156. extern void    ENTRY_POINT (void);
  157. extern char    **ARG_ARRAY;         /* Current argument address    */
  158. extern int    ARG_COUNT;         /* Current argument count    */
  159.  
  160. /*
  161.  * General OS independent start of the command line and program name.
  162.  */
  163.  
  164. #if defined (__OS2__)
  165. char         *_ACmdLine;
  166. char         *_APgmName;         /* Program name            */
  167. #else
  168. #  if defined (OS2)
  169. extern ushort far _aenvseg;
  170. extern ushort far _acmdln;
  171. #  endif
  172. char far    *_ACmdLine;
  173. char far    *_APgmName;         /* Program name            */
  174. #endif
  175.  
  176. /*
  177.  *  MODULE ABSTRACT: _setargv
  178.  *
  179.  *  UNIX like command line expansion
  180.  */
  181.  
  182. /*
  183.  * OS/2 2.x (32-bit) version
  184.  */
  185.  
  186.  
  187. #if defined (__OS2__)
  188. void    ENTRY_POINT (void)
  189. {
  190.     char    *argvp;
  191.     APIRET    rc;
  192.     PTIB    ptib;
  193.     PPIB    ppib;
  194.     char    *MName;
  195.  
  196. /* Get the command line and program name */
  197.  
  198.     if (rc = DosGetInfoBlocks (&ptib, &ppib))
  199.     {
  200.         fprintf (stderr, "DosGetInfoBlocks: Cannot find command line (%d)\n",
  201.          rc);
  202.         exit (1);
  203.     }
  204.  
  205.     if ((MName = malloc (PATH_MAX + NAME_MAX + 3)) == (char *)NULL)
  206.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  207.  
  208.     if (rc = DosQueryModuleName (ppib->pib_hmte, NAME_MAX + PATH_MAX + 2,
  209.                      MName))
  210.     {
  211.         fprintf (stderr, "DosQueryModuleName: Cannot get program name (%d)\n",
  212.          rc);
  213.         exit (1);
  214.     }
  215.  
  216. /* Save the program name and process the command line */
  217.  
  218.     _APgmName = MName;
  219.     _Ex_ProcessEMXArguments (ppib->pib_pchcmd);
  220.  
  221. /* Set up the Window name.  Give up if it does not work.  */
  222.  
  223.     _Ex_SetUpWindowName ();
  224.     _Ex_AddArgument ((char *)NULL);
  225.     --ARG_COUNT;
  226. }
  227.  
  228. #elif defined (OS2)
  229.  
  230. /*
  231.  * OS/2 1.x (16-bit) version
  232.  */
  233.  
  234. void    ENTRY_POINT (void)
  235. {
  236. #  if !defined (M_I86LM) && !defined (__LARGE__)
  237.     char far        *s;         /* Temporary string pointer        */
  238.     char        buf[MAX_LINE];    /* Temporary space        */
  239.     char        *cp;
  240. #  endif
  241.     char far        *argvp = (char far *)((((long)_aenvseg) << 16));
  242.     ushort        off = _acmdln;
  243.  
  244.     while (--off)
  245.     {
  246.     if (argvp[off - 1] == 0)
  247.          break;
  248.     }
  249.  
  250. /* Add program name */
  251.  
  252.     _APgmName =  &argvp[off];
  253.  
  254.     if (argvp[_acmdln] == 0)
  255.     {
  256. #  if !defined (M_I86LM) && !defined (__LARGE__)
  257.     cp = buf;
  258.     s = _APgmName;
  259.     while (*(cp++) = *(s++))
  260.         continue;
  261.  
  262.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
  263. #  else
  264.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (_APgmName));
  265. #  endif
  266.     }
  267.  
  268.     else
  269.     {
  270.     argvp += _acmdln;
  271.  
  272. #  if !defined (M_I86LM) && !defined (__LARGE__)
  273.     cp = buf;
  274.     s = argvp;
  275.     while (*(cp++) = *(s++))
  276.         continue;
  277.  
  278.     off = strlen (buf);
  279.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
  280.     argvp += off + 1;
  281.  
  282.     cp = buf;
  283.     s = argvp;
  284.     while (*(cp++) = *(s++))
  285.         continue;
  286.  
  287.     _Ex_CommandLine (buf);
  288. #  else
  289.     _Ex_ProcessEMXArguments (argvp);
  290. #  endif
  291.     }
  292.  
  293. /* Set up the Window name.  Give up if it does not work.  */
  294.  
  295.     _Ex_SetUpWindowName ();
  296.     _Ex_AddArgument ((char *)NULL);
  297.     --ARG_COUNT;
  298. }
  299.  
  300. #elif (WIN32)
  301.  
  302. /*
  303.  * Windows NT version
  304.  */
  305.  
  306. void    ENTRY_POINT (void)
  307. {
  308.     char    *cline = GetCommandLine ();
  309.     char    *MName;
  310.  
  311. #ifdef TEST
  312.     printf ("Got Command line as |%s|\n", cline);
  313. #endif
  314.  
  315. /* Get the command line and program name */
  316.  
  317.     if (!*cline)
  318.     {
  319.     if ((MName = malloc (MAX_PATH)) == (char *)NULL)
  320.         _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  321.  
  322.     if (!GetModuleFileName (0, MName, MAX_PATH))
  323.     {
  324.         fprintf (stderr, "GetModuleFileName: Cannot get program name (%ld)\n",
  325.              GetLastError ());
  326.         exit (1);
  327.     }
  328.  
  329.     cline = MName;
  330.  
  331. #ifdef TEST
  332.         printf ("Got command program name |%s|\n", cline);
  333. #endif
  334.     }
  335.  
  336. /* Save the program name and process the command line */
  337.  
  338.     _Ex_CommandLine (_ACmdLine = cline);
  339.     _Ex_AddArgument ((char *)NULL);
  340.     _APgmName = _Ex_ConvertToUnixFormat (ARG_ARRAY[0]);
  341.  
  342. /* Set up the Window name.  Give up if it does not work.  */
  343.  
  344.     _Ex_SetUpWindowName ();
  345.     --ARG_COUNT;
  346. }
  347.  
  348. #else
  349.  
  350. /*
  351.  * MSDOS version
  352.  */
  353.  
  354. void    ENTRY_POINT (void)
  355. {
  356.     char far        *s;         /* Temporary string pointer        */
  357.     union REGS        r;
  358.  
  359. #  if !defined (M_I86LM) && !defined (__LARGE__)
  360.     char        buf[MAX_LINE];    /* Temporary space        */
  361. #  endif
  362.                     /* Set up pointer to command line */
  363.     unsigned int    envs = *(int far *)((((long)_psp) << 16) + 0x02cL);
  364.     unsigned int    Length;
  365.  
  366. /* For reasons that escape me, MSC 6.0 does sets up _osmajor and _osminor
  367.  * in the command line parser!
  368.  */
  369.  
  370.    r.h.ah = 0x30;
  371.    intdos (&r, &r);
  372.    _osminor = r.h.ah;
  373.    _osmajor = r.h.al;
  374.  
  375. /* Check the length */
  376.  
  377.     _ACmdLine = (char far *)((((long)_psp) << 16) + 0x080L);
  378.  
  379.     if ((Length = (unsigned int)*(_ACmdLine++)) > 127)
  380.     Length = 127;
  381.  
  382.     _ACmdLine[Length] = 0;
  383.  
  384. /* Command line can be null or 0x0d terminated - convert to null */
  385.  
  386.     if ((s = strchr (_ACmdLine, 0x0d)) != (char *)NULL)
  387.     *s = 0;
  388.  
  389. #ifdef TEST
  390.     printf ("_psp line = <%s>\n", _ACmdLine);
  391. #endif
  392.  
  393. /* Set up global parameters and expand */
  394.  
  395.     ARG_COUNT = 0;
  396.  
  397. /* Get the program name */
  398.  
  399.     if ((_osmajor <= 2) || (envs == 0))
  400.     s = "unknown";
  401.  
  402. /* In the case of DOS 3+, we look in the environment space */
  403.  
  404.     else
  405.     {
  406.     s = (char far *)(((long)envs) << 16);
  407.  
  408.     while (*s)
  409.     {
  410.         while (*(s++) != 0)
  411.         continue;
  412.     }
  413.  
  414.     s += 3;
  415.     }
  416.  
  417. /* Add the program name        */
  418.  
  419.     _APgmName = s;
  420.  
  421. #  if !defined (M_I86LM) && !defined (__LARGE__)
  422.     cp = buf;
  423.     while (*(cp++) = *(s++))
  424.     continue;
  425.  
  426.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
  427.  
  428.     s  = _ACmdLine;
  429.     cp = buf;
  430.     while (*(cp++) = *(s++))
  431.     continue;
  432.  
  433.     _Ex_CommandLine (buf);
  434. #  else
  435.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (s));
  436.     _Ex_CommandLine (_ACmdLine);
  437. #  endif
  438.  
  439.     _Ex_AddArgument ((char *)NULL);
  440.     --ARG_COUNT;
  441. }
  442. #endif
  443.  
  444. /*
  445.  * Expand the DOS Command line
  446.  */
  447.  
  448. static void    _Ex_CommandLine (argvp)
  449. char        *argvp;            /* Line to expand            */
  450. {
  451.     char    *spos;            /* End of string pointer    */
  452.     char    *cpos;            /* Start of string pointer    */
  453.     char    *tpos;
  454.     char    *fn;            /* Extracted file name string    */
  455.  
  456. /* Search for next separator */
  457.  
  458.     spos = argvp;
  459.  
  460.     while (*(cpos = _Ex_SkipWhiteSpace (spos)))
  461.     {
  462.  
  463. /* Extract string argument */
  464.  
  465.     if ((*cpos == '"') || (*cpos == '\''))
  466.     {
  467.         spos = cpos + 1;
  468.  
  469.         do
  470.         {
  471.         if ((spos = strchr (spos, *cpos)) != (char *)NULL)
  472.         {
  473.             spos++;
  474.             if (spos[-2] != '\\')
  475.             break;
  476.         }
  477.  
  478.         else
  479.             spos = &spos[strlen (cpos)];
  480.  
  481.         } while (*spos);
  482.  
  483.         fn    = _Ex_GetSpace (spos - cpos - 2, cpos + 1);
  484.  
  485. /* Remove escaped characters */
  486.  
  487.        tpos = fn;
  488.  
  489.        while ((tpos = strchr (tpos, *cpos)) != (char *)NULL)
  490.            strcpy (tpos - 1, tpos);
  491.     }
  492.  
  493. /* Extract normal argument */
  494.  
  495.     else
  496.     {
  497.         spos = cpos;
  498.         while (!isspace (*spos) && *spos)
  499.         spos++;
  500.  
  501.         fn = _Ex_GetSpace (spos - cpos, cpos);
  502.     }
  503.  
  504. /* Process argument */
  505.  
  506.     if (*cpos != '\'')
  507.         fn = _Ex_ConvertEnvVariables (fn);
  508.  
  509.     switch (*cpos)
  510.     {
  511.         case '@':        /* Expand file                    */
  512.         _Ex_ExpandIndirectFile (fn);
  513.         break;
  514.  
  515.         case '"':        /* Expand string                */
  516.         case '\'':
  517.         _Ex_AddArgument (fn);
  518.         break;
  519.  
  520.         default:        /* Expand field                    */
  521.         _Ex_ExpandField (fn);
  522.     }
  523.  
  524.     free (fn);
  525.     }
  526. }
  527.  
  528. /* Expand an indirect file Argument */
  529.  
  530. static void    _Ex_ExpandIndirectFile (file)
  531. char        *file;        /* Expand file name                */
  532. {
  533.     FILE        *fp;        /* File descriptor                */
  534.     char    *EoLFound;    /* Pointer                */
  535.     int        c_maxlen = MAX_LINE;
  536.     char    *line;        /* Line buffer                    */
  537.     char    *eolp;
  538.  
  539. /* If file open fails, expand as a field */
  540.  
  541. #ifdef __OS2__
  542.     if ((fp = fopen (file + 1, "r")) == NULL)
  543. #else
  544.     if ((fp = fopen (file + 1, "rt")) == NULL)
  545. #endif
  546.     _Ex_FatalError (errno, "%s: Cannot open re-direct file - %s (%s)\n",
  547.             file + 1);
  548.  
  549. /* Grab some memory for the line */
  550.  
  551.     if ((line = malloc (c_maxlen)) == (char *)NULL)
  552.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  553.  
  554. /* For each line in the file, remove EOF characters and add argument */
  555.  
  556.     while (fgets (line, c_maxlen, fp) != (char *)NULL)
  557.     {
  558.     EoLFound = strchr (line, '\n');
  559.     eolp = line;
  560.  
  561. /* Handle continuation characters */
  562.  
  563.     while (TRUE)
  564.     {
  565.  
  566. /* Check for a continuation character */
  567.  
  568.         if (((EoLFound = strchr (eolp, '\n')) != (char *)NULL) &&
  569.         (*(EoLFound - 1) == '\\'))
  570.         {
  571.         *(EoLFound - 1) = '\n';
  572.         *EoLFound = 0;
  573.         EoLFound = (char *)NULL;
  574.         }
  575.  
  576.         else if (EoLFound == (char *)NULL)
  577.         EoLFound = strchr (line, 0x1a);
  578.  
  579.         if (EoLFound != (char *)NULL)
  580.         break;
  581.  
  582. /* Find the end of the line */
  583.  
  584.         c_maxlen = strlen (line);
  585.  
  586. /* Get some more space */
  587.  
  588.         if ((line = realloc (line, c_maxlen + MAX_LINE)) == (char *)NULL)
  589.         _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  590.  
  591.         eolp = &line[c_maxlen];
  592.  
  593.         if (fgets (eolp, MAX_LINE, fp) == (char *)NULL)
  594.         break;
  595.     }
  596.  
  597. /* Terminate the line and add it to the argument list */
  598.  
  599.     if (EoLFound != (char *)NULL)
  600.         *EoLFound = 0;
  601.  
  602.     _Ex_AddArgument (line);
  603.     }
  604.  
  605.     if (ferror(fp))
  606.     _Ex_FatalError (errno, "%s: %s (%s)\n", file + 1);
  607.  
  608.     free (line);
  609.     fclose (fp);
  610.  
  611. /* Delete tempoary files */
  612.  
  613.     if (((line = strrchr (file + 1, '.')) != (char *)NULL) &&
  614.     (stricmp (line, ".tmp") == 0))
  615.     unlink (file + 1);            /* Delete it        */
  616. }
  617.  
  618. /* Get space for an argument name */
  619.  
  620. static char    *_Ex_GetSpace (length, in_s)
  621. int        length;            /* String length                */
  622. char        *in_s;                  /* String address        */
  623. {
  624.     char    *out_s;            /* Malloced space address       */
  625.  
  626.     if ((out_s = malloc (length + 1)) == (char *)NULL)
  627.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  628.  
  629. /* Copy string for specified length */
  630.  
  631.     strncpy (out_s, in_s, length);
  632.     out_s[length] = 0;
  633.  
  634.     return (out_s);
  635. }
  636.  
  637. /* Append an argument to the array */
  638.  
  639. static void    _Ex_AddArgument (Argument)
  640. char        *Argument;            /* Argument to add        */
  641. {
  642.     if (ARG_COUNT == 0)
  643.     ARG_ARRAY = (char **)malloc (50 * S_ENTRY);
  644.  
  645.     else if ((ARG_COUNT % 50) == 0)
  646.     ARG_ARRAY = (char **)realloc (ARG_ARRAY, (ARG_COUNT + 50) * S_ENTRY);
  647.  
  648.     if (ARG_ARRAY == (char **)NULL)
  649.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  650.  
  651.     if (Argument == (char *)NULL)
  652.     ARG_ARRAY[ARG_COUNT++] = (char *)NULL;
  653.  
  654.     else
  655.     ARG_ARRAY[ARG_COUNT++] = _Ex_GetSpace (strlen (Argument), Argument);
  656. }
  657.  
  658. /*  Skip over spaces */
  659.  
  660. static char    *_Ex_SkipWhiteSpace (a)
  661. char        *a;            /* String start address        */
  662. {
  663.     while (isspace(*a))
  664.         a++;
  665.  
  666.     return (a);
  667. }
  668.  
  669. /* Convert name to Unix format */
  670.  
  671. static char    *_Ex_ConvertToUnixFormat (a)
  672. char        *a;
  673. {
  674.     char    *sp = a;
  675.  
  676.     while ((a = strchr (a, '\\')) != (char *)NULL)
  677.     *(a++) = '/';
  678.  
  679. #if !defined (OS2) && !defined (__OS2__) && !defined (WIN32)
  680.     return strlwr (sp);
  681. #else
  682.     if (!IsHPFSFileSystem (sp))
  683.     strlwr (sp);
  684.  
  685.     return sp;
  686. #endif
  687.  
  688. }
  689.  
  690. /* Find the location of meta-characters.  If no meta, add the argument and
  691.  * return NULL.  If meta characters, return position of end of directory
  692.  * name.  If not multiple directories, return -1
  693.  */
  694.  
  695. static void    _Ex_ExpandField (file)
  696. char        *file;
  697. {
  698.     int        i = 0;
  699.     glob_t    gp;
  700.  
  701.     if (strpbrk (file, "?*[]\\") == (char *)NULL)
  702.     {
  703.     _Ex_AddArgument (file);
  704.     return;
  705.     }
  706.  
  707.     if (glob (file, GLOB_NOCHECK, (int (_CDECL *)(char *, int))NULL , &gp))
  708.     _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
  709.  
  710.     i = 0;
  711.  
  712.     while (i < gp.gl_pathc)
  713.     _Ex_AddArgument (gp.gl_pathv[i++]);
  714.  
  715.     globfree (&gp);
  716. }
  717.  
  718. /* Fatal errors */
  719.  
  720. static void    _Ex_FatalError (ecode, format, para)
  721. int        ecode;
  722. char        *format;
  723. char        *para;
  724. {
  725.     fprintf (stderr, format, "stdargv", strerror (ecode), para);
  726.     exit (1);
  727. }
  728.  
  729. /* Process Environment - note that field is a malloc'ed field */
  730.  
  731. static char    *_Ex_ConvertEnvVariables (field)
  732. char        *field;
  733. {
  734.     char    *sp, *cp, *np, *ep;
  735.     char    save;
  736.     int        b_flag;
  737.  
  738.     sp = field;
  739.  
  740. /* Replace any $ strings */
  741.  
  742.     while ((sp = strchr (sp, '$')) != (char *)NULL)
  743.     {
  744.  
  745. /* If ${...}, find the terminating } */
  746.  
  747.     if (*(cp = ++sp) == '{')
  748.     {
  749.         b_flag = 1;
  750.         ++cp;
  751.  
  752.         while (*cp && (*cp != '}'))
  753.         cp++;
  754.     }
  755.  
  756. /* Else must be $..., find the terminating non-alphanumeric */
  757.  
  758.     else
  759.     {
  760.         b_flag = 0;
  761.  
  762.         while (isalnum (*cp))
  763.         cp++;
  764.     }
  765.  
  766. /* Grab the environment variable */
  767.  
  768.     if (cp == sp)
  769.         continue;
  770.  
  771. /* Get its value */
  772.  
  773.     save = *cp;
  774.     *cp = 0;
  775.     ep = getenv (sp + b_flag);
  776.     *cp = save;
  777.  
  778.     if (ep != (char *)NULL)
  779.     {
  780.         np = _Ex_GetSpace (strlen(field) - (cp - sp) + strlen (ep) - 1, field);
  781.         strcpy (&np[sp - field - 1], ep);
  782.         free (field);
  783.         strcpy ((sp = &np[strlen(np)]), cp + b_flag);
  784.         field = np;
  785.     }
  786.     }
  787.  
  788.     return field;
  789. }
  790.  
  791. /*
  792.  * Handle EMX style arguments
  793.  */
  794.  
  795. #if defined (OS2) || defined (__OS2__)
  796. static void    _Ex_ProcessEMXArguments (char *argvp)
  797. {
  798.     char    *cp;
  799.     char    *s = argvp;
  800.  
  801.     _Ex_AddArgument (_Ex_ConvertToUnixFormat (argvp));
  802.     argvp += strlen (argvp) + 1;
  803.     _ACmdLine = argvp;
  804. #ifdef TEST
  805.     printf ("argvp line = <%s>\n", _ACmdLine);
  806. #endif
  807.  
  808. /*
  809.  * Add support in OS2 version for Eberhard Mattes EMX interface to commands.
  810.  */
  811.  
  812.     if ((*argvp) && (*(cp = argvp + strlen (argvp) + 1) == '~') &&
  813.     (strcmp (s, _Ex_ConvertToUnixFormat (cp + 1)) == 0))
  814.     {
  815.  
  816. /* Skip over the program name at string 2 to the start of the first
  817.  * argument at string 3
  818.  */
  819.  
  820.     argvp += strlen (argvp) + 1;
  821.     argvp += strlen (argvp) + 1;
  822.  
  823.     while (*argvp)
  824.     {
  825.         cp = (*argvp == '~') ? argvp + 1 : argvp;
  826.  
  827.         if (*cp == '@')
  828.         _Ex_ExpandIndirectFile (cp);
  829.  
  830.         else
  831.         _Ex_AddArgument (cp);
  832.  
  833.         argvp += strlen (argvp) + 1;
  834.     }
  835.     }
  836.  
  837.     else
  838.     _Ex_CommandLine (argvp);
  839. }
  840.  
  841. /*
  842.  * Set up the Window Name
  843.  */
  844.  
  845. static void    _Ex_SetUpWindowName (void)
  846. {
  847.     HSWITCH        hswitch;
  848.     SWCNTRL        swctl;
  849.     char        *cp;
  850.  
  851.     if (((hswitch = WinQuerySwitchHandle (0, getpid ()))) &&
  852.     (!WinQuerySwitchEntry (hswitch, &swctl)))
  853.     {
  854.     if ((cp = strrchr (ARG_ARRAY[0], '/')) == (char *)NULL)
  855.         cp = ARG_ARRAY[0];
  856.  
  857.     else
  858.         ++cp;
  859.  
  860.     strncpy (swctl.szSwtitle, cp, MAXNAMEL);
  861.     swctl.szSwtitle[MAXNAMEL] = 0;
  862.  
  863.     if ((cp = strrchr (swctl.szSwtitle, '.')) != (char *)NULL)
  864.         *cp = 0;
  865.  
  866.     WinChangeSwitchEntry (hswitch, &swctl);
  867.     }
  868. }
  869. #endif
  870.  
  871. /*
  872.  * Windows NT version
  873.  */
  874.  
  875. #ifdef WIN32
  876. static void    _Ex_SetUpWindowName (void)
  877. {
  878.     char        *cp;
  879.  
  880.     if ((cp = strrchr (ARG_ARRAY[0], '/')) == (char *)NULL)
  881.     cp = ARG_ARRAY[0];
  882.  
  883.     else
  884.     ++cp;
  885.  
  886.     SetConsoleTitle (cp);
  887. }
  888. #endif
  889.  
  890.  
  891. /*
  892.  * Test main program
  893.  */
  894.  
  895. #ifdef TEST
  896. int    main (int argc, char **argv)
  897. {
  898.     int        i;
  899.  
  900.     printf ("_ACmdLine = <%s>\n", _ACmdLine);
  901.  
  902.     for (i = 0; i < argc; i++)
  903.     printf ("Arg %d = |%s|\n", i, argv[i]);
  904.  
  905.     return 0;
  906. }
  907. #endif
  908.